/*! \file
 * \brief Empty.
 * \author Ivo Wingelaar
 * \date 2011
 * \version 0.1.0
 * \copyright GNU Lesser General Public License v3
 */

#ifndef __MYTH_RANDOM_HPP_INCLUDED__
#define __MYTH_RANDOM_HPP_INCLUDED__

#include "MythStream.hpp"

#if (!defined _MYTH_RANDOM_EXTENSION_)
    #if ((!defined _MYTH_RANDOM_STATIC_LIBRARY_) && (!defined _MYTH_RANDOM_DYNAMIC_LIBRARY_))
        #error Please either define "_MYTH_RANDOM_STATIC_LIBRARY_" or "_MYTH_RANDOM_DYNAMIC_LIBRARY_"
    #endif

    #ifdef _MYTH_WINDOWS_
        #ifdef _MYTH_RANDOM_STATIC_LIBRARY_
            #define _MYTH_RANDOM_API_
        #endif // _MYTH_RANDOM_STATIC_LIBRARY_

        #ifdef _MYTH_RANDOM_DYNAMIC_LIBRARY_
            #ifdef _MYTH_RANDOM_EXPORT_
                #define _MYTH_RANDOM_API_ __declspec(dllexport)
            #else
                #define _MYTH_RANDOM_API_ __declspec(dllimport)
            #endif // _MYTH_RANDOM_EXPORT_
        #endif // _MYTH_RANDOM_DYNAMIC_LIBRARY_
    #endif // _MYTH_WINDOWS_

    #ifdef _MYTH_LINUX_
        #define _MYTH_RANDOM_API_
    #endif // _MYTH_LINUX_
#endif // _MYTH_RANDOM_EXTENSION_

namespace Myth
{
namespace Random
{

class Algorithm;

enum E_RANDOM_ALGORITHM
{
    ERA_MOTHER_OF_ALL,
    ERA_MERSENNE_TWISTER_19937,
    ERA_MERSENNE_TWISTER_11213A,
    ERA_SIMD_FAST_MERSENNE_TWISTER_607,
    ERA_SIMD_FAST_MERSENNE_TWISTER_1279,
    ERA_SIMD_FAST_MERSENNE_TWISTER_2281,
    ERA_SIMD_FAST_MERSENNE_TWISTER_4253,
    ERA_SIMD_FAST_MERSENNE_TWISTER_11213,
    ERA_SIMD_FAST_MERSENNE_TWISTER_19937,
    ERA_SIMD_FAST_MERSENNE_TWISTER_44497,
    ERA_SIMD_FAST_MERSENNE_TWISTER_607_MOA,
    ERA_SIMD_FAST_MERSENNE_TWISTER_1279_MOA,
    ERA_SIMD_FAST_MERSENNE_TWISTER_2281_MOA,
    ERA_SIMD_FAST_MERSENNE_TWISTER_4253_MOA,
    ERA_SIMD_FAST_MERSENNE_TWISTER_11213_MOA,
    ERA_SIMD_FAST_MERSENNE_TWISTER_19937_MOA,
    ERA_SIMD_FAST_MERSENNE_TWISTER_44497_MOA,
    ERA_COUNT
};

#if (!defined _MYTH_RANDOM_EXTENSION_)

    extern "C" _MYTH_RANDOM_API_ Algorithm* _MYTH_CALL_CONV_ create_random_algorithm(E_RANDOM_ALGORITHM algo, int32_t seed);

    extern "C" _MYTH_RANDOM_API_ Stream::Input* _MYTH_CALL_CONV_ create_input_random(E_RANDOM_ALGORITHM algo, int32_t seed, const std::string& name);

#endif // _MYTH_RANDOM_EXTENSION_

//! A pseudo-random number generator.
class Algorithm : public virtual ReferenceCounter
{
public:
    //! Virtual destructor.
    virtual ~Algorithm(void)
    {
        //
    }

    //! Initializes the generator with a new seed.
    /*!
     * \param[in] seed The seed to initialize the algorithm with.
     */
    virtual void random_init(int32_t seed) = 0;

    //! Return 32 random bits.
    /*!
     * \return 32 random bits.
     */
    virtual uint32_t get_random_bytes(void) = 0;

    //! Returns a random number in the interval [min, max].
    /*!
     * \return A number in the interval [min, max].
     * \param[in] min The smallest number possible.
     * \param[in] max The largest number possible.
     */
    virtual int32_t get_random_int(int32_t min, int32_t max) = 0;

    //! Returns a random 64 bit floating point value in the interval [0, 1]
    /*!
     * \return A random 64 bit float value in the interval [0, 1].
     */
    virtual double get_random_double(void) = 0;
};

} // namespace Random
} // namespace Myth

#endif // __MYTH_RANDOM_HPP_INCLUDED__
